#include "Semaforo.h"

Semaforo::Semaforo(key_t clave)
{
	this->id = semget(clave, 1, 0666 | IPC_CREAT);
	if(id == -1)
		throw std::string("Error en semget: ") + strerror(errno);
}

Semaforo::Semaforo(const Semaforo & orig) :
id(orig.id)
{
}

Semaforo::~Semaforo()
{
}

int Semaforo::setVal(int valor) const
{
	union semnum
	{
		int val;
		struct semid_ds* buf;
		ushort* array;
	} init;
	init.val = valor;
	int resultado = semctl(this->id, 0, SETVAL, init);
	if(resultado == -1)
		throw std::string("Error en semctl(SETVAL): ") + strerror(errno);
	return resultado;
}

int Semaforo::p() const
{
	struct sembuf operacion;
	operacion.sem_num = 0;	// numero de semaforo
	operacion.sem_op = -1;	// restar 1 al semaforo
	operacion.sem_flg = 0;
	int resultado = semop(this->id, &operacion, 1);
	if(resultado == -1)
		throw std::string("Error en Semaforo::p(): ") + strerror(errno);
	return resultado;
}

int Semaforo::v() const
{
	struct sembuf operacion;
	operacion.sem_num = 0;	// numero de semaforo
	operacion.sem_op = 1;	// sumar 1 al semaforo
	operacion.sem_flg = 0;
	int resultado = semop(this->id, &operacion, 1);
	if(resultado == -1)
		throw std::string("Error en Semaforo::v(): ") + strerror(errno);
	return resultado;
}

void Semaforo::eliminar() const
{
	if(semctl(this->id, 0, IPC_RMID) == -1)
		throw std::string("Error en semctl(IPC_RMID): ") + strerror(errno);
}

Semaforo& Semaforo::operator =(const Semaforo& orig)
{
	id = orig.id;
	return *this;
}

key_t Semaforo::generarClave(const std::string& archivo, char letra)
{
	key_t clave = ftok(archivo.c_str(), letra);
	if (clave == -1)
		throw std::string("Error al generar la clave.");
	return clave;
}
